#ifndef __DCHAR_H__
#define __DCHAR_H__

#include <string>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include "Type.h"

#ifdef _UNICODE
#define DCHAR wchar_t
#define DTEXT(x) L##x
#else
#define DCHAR char
#define DTEXT(x) x
#endif

inline int dstrtoiA(const char *str)
{
	int t = 0;
	int d = 1;
	int i = 0;
	if (str[0] == '-')
	{
		d = -1;
		i++;
	}
	while (str[i])
	{
		if (str[i] >= '0' && str[i] <= '9')
		{
			int tt = str[i] - '0';
			t *= 10;
			t += tt;
		}
		else break;
		i++;
	}
	return t*d;
}
inline int dstrtoiW(const wchar_t *str)
{
	int t = 0;
	int d = 1;
	int i = 0;
	if (str[0] == '-')
	{
		d = -1;
		i++;
	}
	while (str[i])
	{
		if (str[i] >= '0' && str[i] <= '9')
		{
			int tt = str[i] - '0';
			t *= 10;
			t += tt;
		}
		else break;
		i++;
	}
	return t*d;
}

template<class T, class S>
inline int __ditostr(T *str, int size, S num, int base, int witdh)
{
	if (witdh < 1) witdh = 1;
	int len = 0, k = 0;
	T temp;
	if (num < 0)
	{
		num = -num;
		*str = ('-');
		str++;
		len++;
		if (len >= size) return 0;
	}
	while(num)
	{
		temp = (T)(num % base);
		if (temp > 9)
		{
			temp -= 10;
			*str = temp + ('A');
		}
		else
		{
			*str = temp + ('0');
		}
		num /= base;
		str++;
		k++;
		if (len + k >= size) return 0;
	}
	while(witdh > k)
	{
		*str++ = '0';
		k++;
	}
	len += k;
	*str-- = ('\0');
	k--;
	while(k > 0)
	{
		temp = *str;
		*str = *(str - k);
		*(str - k) = temp;
		str--;
		k -= 2;
	}
	return len;
}

template<class T, class S>
inline int __ditostr_unsigned(T *str, int size, S num, int base, int width)
{
	if (width < 1) width = 1;
	int len = 0, k = 0;
	T temp;
	while (num)
	{
		temp = (T)(num % base);
		if (temp > 9)
		{
			temp -= 10;
			*str = temp + ('A');
		}
		else
		{
			*str = temp + ('0');
		}
		num /= base;
		str++;
		k++;
		if (len + k >= size) return 0; 
	}
	while (width > k)
	{
		*str++ = ('0');
		k++;
	}
	len += k;
	*str-- = ('\0');
	k--;
	while (k > 0)
	{
		temp = *str;
		*str = *(str - k);
		*(str - k) = temp;
		str--;
		k -= 2;
	}
	return len;
}

inline int ditostrA(char *str, int size, int num, int base = 10, int width = 1)
{
	return __ditostr<char, int>(str, size, num, base, width);
}
inline int ditostrW(wchar_t *str, int size, int num, int base = 10, int width = 1)
{
	return __ditostr<wchar_t, int>(str, size, num, base, width);
}
inline int dutostrA(char *str, int size, unsigned int num, int base = 10, int width = 1)
{
	return __ditostr_unsigned<char, unsigned int>(str, size, num, base, width);
}
inline int dutostrW(wchar_t *str, int size, int num, int base = 10, int width = 1)
{
	return __ditostr_unsigned<wchar_t, unsigned int>(str, size, num, base, width);
}
inline int di64tostrA(char *str, int size, long long num, int base = 10, int width = 1)
{
	return __ditostr<char, long long>(str, size, num, base, width);
}
inline int di64tostrW(wchar_t *str, int size, long long num, int base = 10, int width = 1)
{
	return __ditostr<wchar_t, long long>(str, size, num, base, width);
}
inline void dstrcpyA(char *dest, int dest_size, const char *source)
{
	int i = 0;
	while (dest_size)
	{
		dest[i] = source[i];
		if (!source[i]) break;
		i++;
		dest_size--;
	}
}
inline void dstrcpyW(wchar_t *dest, int dest_size, const wchar_t *source)
{
	int i = 0;
	while (dest_size)
	{
		dest[i] = source[i];
		if (!source[i]) break;
		i++;
		dest_size--;
	}
}
inline int dstrlen(const DCHAR *str)
{
	int r = 0;
	while (str[r]) r++;
	return r;
}
inline int dstrlenW(const wchar_t *str)
{
	int r = 0;
	while (str[r]) r++;
	return r;
}
inline void dstrcatA(char *dest, int size, const char * str)
{
	int i = 0;
	while (dest[i]) i++;
	for (int j = 0;;j++)
	{
		if (i >= size)
		{
			if (i) dest[i-1] = 0;
			return;
		}
		dest[i] = str[j];
		i++;
		if (str[j] == 0) break;
	}
}
inline void dstrcatW(wchar_t *dest, int size, const wchar_t * str)
{
	int i = 0;
	while (dest[i]) i++;
	for (int j = 0;;j++)
	{
		if (i >= size)
		{
			if (i) dest[i-1] = 0;
			return;
		}
		dest[i] = str[j];
		i++;
		if (str[j] == 0) break;
	}
}
inline void dmemset(void *p, int n, int size)
{
	while (size)
	{
		size--;
		((unsigned char*)p)[size] = n;
	}
}
inline void dmemcpy(void *pDest, const void *pSource, int nLen)
{
	for (int i = 0; i < nLen; i++)
	{
		((char*)pDest)[i] = ((char*)pSource)[i];
	}
}
inline int dstrcmpA(const char * p1, const char * p2)
{
	for (int i = 0; ; i++)
	{
		if (p1[i] < p2[i]) return -1;
		else if (p1[i] > p2[i]) return 1;
		if (p1[i] == 0) break;
	}
	return 0;
}
inline int dstrcmpW(const wchar_t * p1, const wchar_t * p2)
{
	for (int i = 0; ; i++)
	{
		if (p1[i] < p2[i]) return -1;
		else if (p1[i] > p2[i]) return 1;
		if (p1[i] == 0) break;
	}
	return 0;
}
inline int dstricmpA(const char * p1, const char * p2)
{
	for (int i = 0; ; i++)
	{
		char a = p1[i];
		if (a >= 'a' && a <= 'z') a = a & 0xDF;
		char b = p2[i];
		if (b >= 'a' && b <= 'z') b = b & 0xDF;
		if (a < b) return -1;
		else if (a > b) return 1;
		if (a == 0) break;
	}
	return 0;
}
inline int dstricmpW(const wchar_t * p1, const wchar_t * p2)
{
	for (int i = 0; ; i++)
	{
		char a = p1[i];
		if (a >= 'a' && a <= 'z') a = a & 0xDF;
		char b = p2[i];
		if (b >= 'a' && b <= 'z') b = b & 0xDF;
		if (a < b) return -1;
		else if (a > b) return 1;
		if (a == 0) break;
	}
	return 0;
}
void dsprintfA(char * szBuffer, int size, const char * szFormat, ...);
void dsprintfW(wchar_t * szBuffer, int size, const wchar_t * szFormat, ...);
void dsprintfArgA(char * szBuffer, int size, const char * szFormat, va_list pArgList);
void dsprintfArgW(wchar_t * szBuffer, int size, const wchar_t * szFormat, va_list pArgList);
float dstrtofA(const char * str);
float dstrtofW(const wchar_t * str);
long long dstrtoi64A(const char * str, int base = 10);
long long dstrtoi64W(const wchar_t * str, int base = 10);
STRING dUnicode2MultiByte(const wchar_t * str);
WSTRING dMultiByte2Unicode(const char * str);

#ifdef _UNICODE
#define dstrtof dstrtofW
#define dstrtoi64 dstrtoi64W
#define dsprintf dsprintfW
#define dstrcpy dstrcpyW
#define dstrcat dstrcatW
#define dstrtoi dstrtoiW
#else
#define dstrtof dstrtofA
#define dstrtoi64 dstrtoi64A
#define dsprintf dsprintfA
#define dstrcpy dstrcpyA
#define dstrcat dstrcatA
#define dstrtoi dstrtoiA
#endif

#endif //__DCHAR_H__
